﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using UlsStudio.AppCore;

namespace UlsStudio.DesktopApp
{
    public partial class StartFarmMonitoringForm : Form
    {
        #region Constructor & Privates

        const string SEP = ";";
        public StartFarmMonitoringForm()
        {
            InitializeComponent();
        }
        #endregion

        void UpdateDisplayState()
        {
            bool couldEnable = lstDirs.Items.Count > 0;
            

            if (this.MainForm.AppEngine.UlsData.WatcherRunning)
            {
                lblMonitoringStatus.Text = "running";
                btnStart.Enabled = false;
                btnStop.Enabled = true;
                btnRemove.Enabled = false;
            }
            else
            {
                lblMonitoringStatus.Text = "stopped";
                btnRemove.Enabled = lstDirs.SelectedItems.Count > 0;
                btnStart.Enabled = couldEnable;
                btnStop.Enabled = false;
            }

            btnAdd.Enabled = !btnStop.Enabled;
        }

        #region Event Handlers

        #region Clicks

        private void btnAdd_Click(object sender, EventArgs e)
        {
            SelectDatasourceForm f = new SelectDatasourceForm();
            f.FormMode = DatasourceSelectMode.DirectoriesOnly;
            if (f.ShowDialog() == DialogResult.OK)
            {
                string selectedDirString = Environment.ExpandEnvironmentVariables(f.SelectedDirectory.FullName);
                DirectoryInfo selectedDir = new DirectoryInfo(selectedDirString);
                foreach (DirListViewItem lvi in lstDirs.Items)
                {
                    // Trim last \ if necesary
                    if (lvi.Dir.FullName.TrimEnd(@"\".ToCharArray()) == selectedDir.FullName.TrimEnd(@"\".ToCharArray()))
                    {
                        MessageBox.Show("This folder has already been added - please pick another one.", "Oops", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                        return;
                    }
                }
                lstDirs.Items.Add(new DirListViewItem(selectedDir));
            }
            UpdateDisplayState(); // Refresh display state
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            foreach (int removeIndex in lstDirs.SelectedIndices)
            {
                lstDirs.Items.RemoveAt(removeIndex);
            }
            UpdateDisplayState(); // Refresh display state
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            Go();
        }
        private void btnStop_Click(object sender, EventArgs e)
        {
            // Update GUI on mainthread
            if (InvokeRequired)
            {
                Invoke(new Action<object, EventArgs>(btnStop_Click), sender, e);
                return;
            };

            // Do stuff on main thread
            this.Cursor = Cursors.WaitCursor;
            this.MainForm.AppEngine.UlsData.WatcherStopped += UlsData_WatcherStopped;         // Wait for stop confirmation
            this.MainForm.AppEngine.UlsData.StopLogMonitoring();

        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void lstDirs_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateDisplayState();
        }

        #endregion

        #region Threads

        void UlsData_WatcherStopped(object sender, EventArgs e)
        {
            // Update GUI on mainthread
            if (InvokeRequired)
            {
                Invoke(new Action<object, EventArgs>(UlsData_WatcherStopped), sender, e);
                return;
            };

            // Do stuff on main thread - complete STOP operation
            this.Cursor = Cursors.Default;
            this.MainForm.AppEngine.UlsData.WatcherStopped -= UlsData_WatcherStopped;
            UpdateDisplayState();
        }

        private void settingsLoader_DoWork(object sender, DoWorkEventArgs e)
        {
            // Turn settings into validated directory-list
            List<DirectoryInfo> dirs = new List<DirectoryInfo>();

            string foldersString = Properties.Settings.Default.LastMonitorFolders;
            if (!string.IsNullOrEmpty(foldersString))
            {
                string[] folders = foldersString.Split(SEP.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach (string folderString in folders)
                {
                    dirs.Add(new DirectoryInfo(folderString));
                }
            }

            e.Result = dirs;
        }

        private void settingsLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.Cursor = Cursors.Default;
            lstDirs.Items.Clear();
            if (e.Result is List<DirectoryInfo>)
            {
                List<DirectoryInfo> results = (List<DirectoryInfo>)e.Result;
                foreach (DirectoryInfo dir in results)
                {
                    lstDirs.Items.Add(new DirListViewItem(dir));
                }
            }
            else
            {
                MessageBox.Show("Couldn't read previous folder settings", "Oops", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }

            this.Enabled = true;
            UpdateDisplayState();
        }

        #endregion

        private void StartFarmMonitoringForm_Load(object sender, EventArgs e)
        {
            lstDirs.Items.Clear();
            lstDirs.Items.Add("Loading & validating last folder list...please wait...");
            UpdateDisplayState();
            this.Enabled = false;
            this.Cursor = Cursors.WaitCursor;

            // Get/validate settings
            settingsLoader.RunWorkerAsync();
        }

        #endregion

        #region Properties

        public List<DirectoryInfo> SelectedDirs { get; set; }

        public MainForm MainForm { get; set; }

        #endregion

        /// <summary>
        /// Start monitoring
        /// </summary>
        private void Go()
        {
            this.Cursor = Cursors.WaitCursor;
            groupBox1.Enabled = false;

            Application.DoEvents();

            // Get list of dirs added
            List<DirectoryInfo> dirs = new List<DirectoryInfo>();
            foreach (DirListViewItem lvi in lstDirs.Items)
            {
                if (lvi.Dir.Exists)
                {
                    dirs.Add(lvi.Dir);
                }
                else
                {
                    this.Cursor = Cursors.Default;
                    groupBox1.Enabled = true;
                    MessageBox.Show(lvi.Dir.FullName + " does not exist!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }
            

            // Save settings
            string folderSettings = string.Empty;
            foreach (DirectoryInfo validatedDir in dirs)
            {
                folderSettings += string.Format("{0}{1}", validatedDir.FullName, SEP);
            }
            folderSettings = folderSettings.TrimEnd(SEP.ToCharArray());
            Properties.Settings.Default.LastMonitorFolders = folderSettings;
            Properties.Settings.Default.Save();

            // Set vars
            this.SelectedDirs = dirs;
            this.DialogResult = System.Windows.Forms.DialogResult.OK;

            // Bye
            this.Close();
            this.Cursor = Cursors.Default;
        }

        #region Private Classes

        class DirListViewItem : ListViewItem
        {
            public DirListViewItem(DirectoryInfo dir)
            {
                this.Dir = dir;

                this.Text = dir.FullName;
                this.ImageIndex = 0;
            }
            public DirectoryInfo Dir { get; set; }
        }

        #endregion
    }
}
